package com.platform.qujia.service.impl;

import cn.hutool.crypto.asymmetric.SignAlgorithm;
import cn.hutool.http.HttpRequest;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.platform.qujia.ApiConst;
import com.platform.qujia.config.BasicInfo;
import com.platform.qujia.pojo.PayOrder;
import com.platform.qujia.service.DeviceService;
import com.platform.qujia.utils.HttpUtil;
import com.platform.qujia.utils.HttpUtils;
import com.platform.qujia.utils.RSASignature;
import com.platform.qujia.utils.StringUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import springfox.documentation.spring.web.json.Json;

import java.io.IOException;
import java.security.*;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.*;

@Service
@Slf4j
public class DeviceServiceImpl implements DeviceService {

    @Value("${voiceBoxCloud.agent_id}")
    private String agentId;

    @Value("${voiceBoxCloud.agent_secret}")
    private String agentSecret;

    @Value("${voiceBoxCloud.url}")
    private String url;

    @Override
    @Async
    public String voiceBroadcast(String deviceCode, String content)  {
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("agent_id",agentId);
        jsonObject.put("agent_secret",agentSecret);
        jsonObject.put("sbx_id",deviceCode);
        jsonObject.put("msg",content);
        jsonObject.put("debug","0");
        log.info("云喇叭终端号{}",deviceCode);
        String body = HttpRequest.post(url).header("Content-Type", "application/json").body(jsonObject.toString()).execute().body();
        log.info("云喇叭返回值{}",body);
        return body;


    }

    @Override
    public String syncVoiceBroadcast(String deviceCode, String content) {
        return this.voiceBroadcast(deviceCode,content);
    }

    @Override
    public String voiceBroadcastLoudspeaker(String msgId, String sn, String transactionId,
                                            String content, String totalFee, String payType, String discountFee,
                                            String attach, String lang, String nonce, String timestamp) {
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("appId",BasicInfo.LOUDSPEAKER_APPID);
        jsonObject.put("msgId",msgId);
        jsonObject.put("sn",sn);
        if(StringUtils.isNotEmpty(transactionId)){
            jsonObject.put("transactionId",transactionId);
        }
        jsonObject.put("content",content);
        jsonObject.put("totalFee",totalFee);

        if(StringUtils.isNotEmpty(payType)){
            jsonObject.put("payType",payType);
        }

        if(StringUtils.isNotEmpty(discountFee)){
            jsonObject.put("discountFee",discountFee);
        }

        if(StringUtils.isNotEmpty(attach)){
            jsonObject.put("attach",attach);
        }

        if(StringUtils.isNotEmpty(lang)){
            jsonObject.put("lang",lang);
        }


        jsonObject.put("nonce",nonce);
        jsonObject.put("timestamp",timestamp);
        Map<String,String> map = JSON.parseObject(jsonObject.toString(), Map.class);
        String s = putPairsSequenceAndTogether(map);
        String body ="";
        String sign = null;
        try {
            log.info(s);
            sign = sign256(s.getBytes("UTF-8"), BasicInfo.LOUDSPEAKER_PRIVATE_KEY);
            //sign = RSASignature.encryptBASE64(RSASignature.sign(s, BasicInfo.LOUDSPEAKER_PRIVATE_KEY));
            jsonObject.put("sign",sign);
            log.info("大音响设备号{}",sn);
            log.info(jsonObject.toString());
            body = HttpRequest.post(BasicInfo.LOUDSPEAKER_URL).header("Content-Type", "application/json").body(jsonObject.toString()).execute().body();
            log.info("大音响设备返回值{}",body);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return body;
    }

    public static String putPairsSequenceAndTogether(Map<String, String> info) {
        List<Map.Entry<String, String>> infoIds = new ArrayList<Map.Entry<String, String>>(info.entrySet());
        Collections.sort(infoIds, new Comparator<Map.Entry<String, String>>() {
            @Override
            public int compare(Map.Entry<String, String> arg0, Map.Entry<String, String> arg1) {
                return (arg0.getKey()).compareTo(arg1.getKey());
            }
        });
        String ret = "";
        for (Map.Entry<String, String> entry : infoIds) {
            ret += entry.getKey();
            ret += "=";
            ret += entry.getValue();
            ret += "&";
        }
        ret = ret.substring(0, ret.length() - 1);
        return ret;
    }
    // 算法类别
    private final static String SIGN_TYPE = "RSA";
    // 算法位数
    private final static Integer KEY_SIZE = 2048;
    /**
     * 签名
     */
    public static String sign256(byte[] signData, String priKey) {
        try {
            byte[] keyBytes = Base64.getDecoder().decode(priKey);
            PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(keyBytes);
            KeyFactory keyFactory = KeyFactory.getInstance(SIGN_TYPE);
            PrivateKey privateKey = keyFactory.generatePrivate(keySpec);
            Signature si = Signature.getInstance(SignAlgorithm.SHA256withRSA.getValue());
            si.initSign(privateKey);
            si.update(signData);
            byte[] sign = si.sign();
            return Base64.getEncoder().encodeToString(sign);
        } catch (Exception e) {
            throw new RuntimeException(e.getMessage());
        }
    }

    /**
     * 验签
     */
    public static boolean verify256(byte[] dataBytes, String sign, String pubkey) {
        boolean flag = false;
        try {
            byte[] signByte = Base64.getDecoder().decode(sign);
            byte[] encodedKey = Base64.getDecoder().decode(pubkey);
            Signature verf = Signature.getInstance(SignAlgorithm.SHA256withRSA.getValue());
            KeyFactory keyFac = KeyFactory.getInstance(SIGN_TYPE);
            PublicKey puk = keyFac.generatePublic(new X509EncodedKeySpec(encodedKey));
            verf.initVerify(puk);
            verf.update(dataBytes);
            flag = verf.verify(signByte);
        } catch (Exception e) {
            throw new RuntimeException(e.getMessage());
        }
        return flag;
    }




}
